package cn.taobaoke.restful;

import cn.taobaoke.restful.datasource.DynamicDataSourceContextHolder;
import cn.taobaoke.restful.domain.*;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ImportService {

    static final String ORIGIN_DATASOURCE = "tbk_background";

    public void import2NewDatabase(final String domain, final Long domainId) {
        logger.info("=========== Start to import [{}] ===========", domain);
        long begin = System.currentTimeMillis();

        long start = System.currentTimeMillis();
        List<AdminEntity> adminEntityList = exportService.getAdmins(domain);
        List<AdminEntity1> adminEntity1s = new ArrayList<>(adminEntityList.size());
        adminEntityList.forEach(e -> {
            AdminEntity1 entity1 = new AdminEntity1(e, domainId);
            entity1.setId(null);
            adminEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        admin1Repository.saveAll(adminEntity1s);

        long end = System.currentTimeMillis();
        logger.info("tb_admin: {} {}(ms)", adminEntity1s.size(), end - start);
        start = System.currentTimeMillis();


        /** ========= 插入Agent表，同时更新PID和Account的agentId START ========== */

        Map<Long, Long> table = new HashMap<>();

        List<AgentEntity> agentEntityList = exportService.getAgents(domain);

        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        for (AgentEntity entity : agentEntityList) {
            AgentEntity1 entity1 = new AgentEntity1(entity, domainId);
            entity1.setId(null);
            entity1 = agent1Repository.save(entity1);
            table.put(entity.getId(), entity1.getId());
        }

//        List<AgentEntity1> agentEntity1s = agent1Repository.findAll();
        List<AgentEntity1> agentEntity1s = agent1Repository.findAllByDomainId(domainId);
        for (AgentEntity1 entity1 : agentEntity1s) {
            entity1.setParentId(table.get(entity1.getParentId()));
            entity1.setGrandParentId(table.get(entity1.getGrandParentId()));
        }
        agent1Repository.saveAll(agentEntity1s);

        end = System.currentTimeMillis();
        logger.info("tb_agent: {} {}(ms)", agentEntityList.size(), end - start);
        start = System.currentTimeMillis();

        List<PIDEntity> pidEntityList = exportService.getPIDs(domain);
        List<PIDEntity1> pidEntity1s = new ArrayList<>(pidEntityList.size());
        pidEntityList.forEach(e -> {
            PIDEntity1 entity1 = new PIDEntity1(e, domainId);
            entity1.setAgentId(table.get(e.getAgentId()));
            entity1.setId(null);
            pidEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        pid1Repository.saveAll(pidEntity1s);

        end = System.currentTimeMillis();
        logger.info("tb_pid: {} {}(ms)", pidEntity1s.size(), end - start);
        start = System.currentTimeMillis();

        List<AccountsEntity> accountsEntityList = exportService.getAccounts(domain);
        List<AccountsEntity1> accountsEntity1s = new ArrayList<>(accountsEntityList.size());
        accountsEntityList.forEach(e -> {
            AccountsEntity1 entity1 = new AccountsEntity1(e, domainId);
            entity1.setAgentId(table.get(e.getAgentId()));
            entity1.setId(null);
            accountsEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        accounts1Repository.saveAll(accountsEntity1s);

        end = System.currentTimeMillis();
        logger.info("tb_account: {} {}(ms)", accountsEntity1s.size(), end - start);
        start = System.currentTimeMillis();

        /** ========= 插入Agent表，同时更新PID和Account的agentId END ========== */

        List<DocumentEntity> documentEntities = exportService.getDocuments(domain);
        List<DocumentEntity1> documentEntity1s = new ArrayList<>(documentEntities.size());
        documentEntities.forEach(e -> {
            DocumentEntity1 entity1 = new DocumentEntity1(e, domainId);
            entity1.setId(null);
            documentEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        document1Repository.saveAll(documentEntity1s);

        end = System.currentTimeMillis();
        logger.info("tb_document: {} {}(ms)", documentEntity1s.size(), end - start);
        start = System.currentTimeMillis();

        List<GlobalConfig> globalConfigList = exportService.getGlobalConfigs(domain);
        List<GlobalConfig1> globalConfig1s = new ArrayList<>(globalConfigList.size());
        globalConfigList.forEach(e -> {
            GlobalConfig1 entity1 = new GlobalConfig1(e, domainId);
            entity1.setId(null);
            globalConfig1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        globalConfig1Repository.saveAll(globalConfig1s);

        end = System.currentTimeMillis();
        logger.info("tb_global: {} {}(ms)", globalConfig1s.size(), end - start);
        start = System.currentTimeMillis();

        List<NoticeEntity> noticeEntities = exportService.getNotices(domain);
        List<NoticeEntity1> noticeEntity1s = new ArrayList<>(noticeEntities.size());
        noticeEntities.forEach(e -> {
            NoticeEntity1 entity1 = new NoticeEntity1(e, domainId);
            entity1.setId(null);
            noticeEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        notice1Repository.saveAll(noticeEntity1s);

        end = System.currentTimeMillis();
        logger.info("tb_notice: {} {}(ms)", noticeEntity1s.size(), end - start);
        start = System.currentTimeMillis();

        List<OrderEntity> orderEntities = exportService.getOrders(domain);
        List<OrderEntity1> orderEntity1s = new ArrayList<>(orderEntities.size());
        orderEntities.forEach(e -> {
            OrderEntity1 entity1 = new OrderEntity1(e, domainId);
            entity1.setId(null);
            entity1.setParentId(table.get(entity1.getParentId()));
            entity1.setPromoterId(table.get(entity1.getPromoterId()));
            entity1.setGrandParentId(table.get(entity1.getGrandParentId()));
            orderEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        orderV2Repository.saveAll(orderEntity1s, domain);

        end = System.currentTimeMillis();
        logger.info("tb_order_{}: {} {}(ms)", domain, orderEntity1s.size(), end - start);
        start = System.currentTimeMillis();

        List<RobotEntity> robotEntities = exportService.getRobots(domain);
        List<RobotEntity1> robotEntity1s = new ArrayList<>(robotEntities.size());
        robotEntities.forEach(e -> {
            RobotEntity1 entity1 = new RobotEntity1(e, domainId);
            entity1.setId(null);
            robotEntity1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        robot1Repository.saveAll(robotEntity1s);

        end = System.currentTimeMillis();
        logger.info("tb_robot: {} {}(ms)", robotEntity1s.size(), end - start);

        start = System.currentTimeMillis();

        /** ==============  ============== */

        List<WxGroupEntity> wxGroupEntities = exportService.getWxGroups(domain);
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        Map<Long, Long> wxGroupMap = new HashMap<>(wxGroupEntities.size());
        wxGroupEntities.forEach(e -> {
            WxGroupEntity1 entity1 = new WxGroupEntity1(e, domainId);
            entity1.setId(null);
            entity1.setAgentId(table.get(entity1.getAgentId()));
            entity1 = wxGroup1Repository.save(entity1);
            wxGroupMap.put(e.getId(), entity1.getId());
        });

        end = System.currentTimeMillis();
        logger.info("tb_wx_group: {} {}(ms)", wxGroupEntities.size(), end - start);

        start = System.currentTimeMillis();

        List<UserEntity> userEntities = exportService.getUsers(domain);
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        Map<Long, Long> userMap = new HashMap<>(userEntities.size());
        userEntities.forEach(e -> {
            UserEntity1 entity1 = new UserEntity1(e, domainId);
            entity1.setId(null);
            entity1 = user1Repository.save(entity1);
            userMap.put(e.getId(), entity1.getId());
        });

        end = System.currentTimeMillis();
        logger.info("tb_user: {} {}(ms)", userEntities.size(), end - start);
        start = System.currentTimeMillis();

        List<AgentGroupRelation> agentGroupRelationList = exportService.getAgentGroupRations(domain);
        List<AgentGroupRelation1> agentGroupRelation1s = new ArrayList<>(agentGroupRelationList.size());
        agentGroupRelationList.forEach(e -> {
            AgentGroupRelation1 entity1 = new AgentGroupRelation1(e, domainId);
            entity1.setId(null);
            entity1.setAgentId(table.get(entity1.getAgentId()));
            entity1.setGroupId(wxGroupMap.get(entity1.getGroupId()));
            agentGroupRelation1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        agentGroupRelation1Repository.saveAll(agentGroupRelation1s);

        end = System.currentTimeMillis();
        logger.info("tb_agent_group_relation: {} {}(ms)", agentGroupRelation1s.size(), end - start);
        start = System.currentTimeMillis();

        List<UserGroupRelation> userGroupRelations = exportService.getUserGroupRelations(domain);
        List<UserGroupRelation1> userGroupRelation1s = new ArrayList<>(userGroupRelations.size());
        userGroupRelations.forEach(e -> {
            UserGroupRelation1 entity1 = new UserGroupRelation1(e, domainId);
            entity1.setId(null);
            entity1.setUserId(userMap.get(entity1.getUserId()));
            entity1.setGroupId(userMap.get(entity1.getGroupId()));
            userGroupRelation1s.add(entity1);
        });
        DynamicDataSourceContextHolder.setDataSourceType(ORIGIN_DATASOURCE);
        userGroupRelation1Repository.saveAll(userGroupRelation1s);

        end = System.currentTimeMillis();
        logger.info("tb_user_group_relation: {} {}(ms)", userGroupRelation1s.size(), end - start);

        /** ==============  ============== */

        long finish = System.currentTimeMillis();
        logger.info("=========== Finish import {}, total {}(ms) ===========", domain, finish - begin);
    }

    private final @NonNull cn.taobaoke.restful.domain.Accounts1Repository accounts1Repository;
    private final @NonNull cn.taobaoke.restful.domain.Admin1Repository admin1Repository;
    private final @NonNull cn.taobaoke.restful.domain.Agent1Repository agent1Repository;

    private final @NonNull cn.taobaoke.restful.domain.Document1Repository document1Repository;
    private final @NonNull cn.taobaoke.restful.domain.GlobalConfig1Repository globalConfig1Repository;
    private final @NonNull cn.taobaoke.restful.domain.Notice1Repository notice1Repository;
    private final @NonNull cn.taobaoke.restful.domain.OrderV2Repository orderV2Repository;
    private final @NonNull cn.taobaoke.restful.domain.PID1Repository pid1Repository;
    private final @NonNull cn.taobaoke.restful.domain.Robot1Repository robot1Repository;

    private final @NonNull cn.taobaoke.restful.domain.AgentGroupRelation1Repository agentGroupRelation1Repository;
    private final @NonNull cn.taobaoke.restful.domain.User1Repository user1Repository;
    private final @NonNull cn.taobaoke.restful.domain.UserGroupRelation1Repository userGroupRelation1Repository;
    private final @NonNull cn.taobaoke.restful.domain.WxGroup1Repository wxGroup1Repository;

    //    private final @NonNull OrderRepository orderRepository;

    private final @NonNull ExportService exportService;

    private Logger logger = LoggerFactory.getLogger(ImportService.class);
}
